package core.android.qrcode;

import android.graphics.Bitmap;
import android.graphics.Rect;
import android.hardware.Camera;
import android.util.Log;
import android.view.View;
import android.widget.ImageView;

import com.google.zxing.BinaryBitmap;
import com.google.zxing.NotFoundException;
import com.google.zxing.PlanarYUVLuminanceSource;
import com.google.zxing.Result;
import com.google.zxing.ResultPointCallback;
import com.google.zxing.common.HybridBinarizer;

import core.android.qrcode.decode.QRDecoder;
import core.android.qrcode.encode.QREncoder;
import core.android.tools.AK;

/**
 * @作者: XQ
 * @创建时间：16-1-8 下午5:41
 * @类说明:二维码工具类 gradle: compile 'com.google.zxing:core:3.2.1'
 */
public class AKQRCodeUtil {

    /**
     * 生成二维码图片
     *
     * @param codemsg
     * @param bitmapSize
     * @return
     */
    public static Bitmap generateQRCode(String codemsg, int bitmapSize) {
        QREncoder mEncoder = new QREncoder.Builder()
                .setBackgroundColor(0xFFFFFF)
                .setCodeColor(0xFF000000)
                .setOutputBitmapPadding(0)
                .setOutputBitmapWidth(bitmapSize)
                .setOutputBitmapHeight(bitmapSize)
                .build();
        return mEncoder.encode(codemsg);
    }

    /**
     * 用于扫描本地图片二维码或者一维码
     * 不需要开新线程，直接主线程跑就可以
     */
    public static Result scanImage(Bitmap bitmap) {
        return  QRDecoder.INSTANCE.decode(bitmap);
    }

    public static Result decodeCameraPreview(byte[] data, Camera camera) {
        if (camera == null) {
            AK.e("camera不能为空！");
            return null;
        }
        Camera.Size size = camera.getParameters().getPreviewSize();
        // 这里需要将获取的data翻转一下，因为相机默认拿的的横屏的数据
        byte[] rotatedData = new byte[data.length];
        for (int y = 0; y < size.height; y++) {
            for (int x = 0; x < size.width; x++)
                rotatedData[x * size.height + size.height - y - 1] = data[x + y * size.width];
        }

        // 宽高也要调整
        int tmp = size.width;
        size.width = size.height;
        size.height = tmp;

        Result rawResult = null;
        PlanarYUVLuminanceSource source = new PlanarYUVLuminanceSource(rotatedData, size.width, size.height, 0, 0, size.width, size.height, false);
        BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
        try {
            rawResult =  QRDecoder.INSTANCE.decodeWithState(bitmap);
        } catch (NotFoundException e) {
            e.printStackTrace();
        }
        return rawResult;
    }

    public static Result decodeCameraPreview(byte[] data, Camera camera, ResultPointCallback resultPointCallback) {
        if (camera == null) {
            AK.e("camera不能为空！");
            return null;
        }
        Camera.Size size = camera.getParameters().getPreviewSize();
        // 这里需要将获取的data翻转一下，因为相机默认拿的的横屏的数据
        byte[] rotatedData = new byte[data.length];
        for (int y = 0; y < size.height; y++) {
            for (int x = 0; x < size.width; x++)
                rotatedData[x * size.height + size.height - y - 1] = data[x + y * size.width];
        }

        // 宽高也要调整
        int tmp = size.width;
        size.width = size.height;
        size.height = tmp;

        Result rawResult = null;
        PlanarYUVLuminanceSource source = new PlanarYUVLuminanceSource(rotatedData, size.width, size.height, 0, 0, size.width, size.height, false);
        BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
        try {
            rawResult = QRDecoder.INSTANCE.addResultPoint(resultPointCallback).decodeWithState(bitmap);
        } catch (NotFoundException e) {
            e.printStackTrace();
        }
        return rawResult;
    }


    /**
     * 解码相机预览数据
     *
     * @param data
     * @param size
     * @param qrcodeRect 截取的矩形区域的坐标文件
     */
    public Result decode(byte[] data, Camera.Size size, Rect qrcodeRect) {
        // 这里需要将获取的data翻转一下，因为相机默认拿的的横屏的数据
        byte[] rotatedData = new byte[data.length];
        for (int y = 0; y < size.height; y++) {
            for (int x = 0; x < size.width; x++)
                rotatedData[x * size.height + size.height - y - 1] = data[x + y * size.width];
        }

        // 宽高也要调整
        int tmp = size.width;
        size.width = size.height;
        size.height = tmp;

        Result rawResult = null;
        PlanarYUVLuminanceSource source = buildLuminanceSource(rotatedData, size.width, size.height, qrcodeRect);
        if (source != null) {
            BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
            try {
                rawResult =  QRDecoder.INSTANCE.decodeWithState(bitmap);
            } catch (Exception re) {
                // continue
            }
        }
        Log.e(getClass().getName(), "扫描结果：rawResult=" + rawResult);
        return rawResult;
    }


    /**
     * A factory method to build the appropriate LuminanceSource object based on
     * the format of the preview buffers, as described by Camera.Parameters.
     *
     * @param data   A preview frame.
     * @param width  The width of the image.
     * @param height The height of the image.
     * @param rect   截取的矩形区域的坐标文件
     * @return A PlanarYUVLuminanceSource instance.
     */
    public PlanarYUVLuminanceSource buildLuminanceSource(byte[] data, int width, int height, Rect rect) {
        if (rect == null) {
            return null;
        }
        // Go ahead and assume it's YUV rather than die.
        return new PlanarYUVLuminanceSource(data, width, height, rect.left, rect.top, rect.width(), rect.height(), false);
    }

    /**
     * 初始化截取的矩形区域
     */
    public Rect getScanRect(ImageView scanCropView, View scanContainer, int cameraWidth, int cameraHeight, int StatusBarHeight) {
//        int cameraWidth = cameraManager.getCameraResolution().y;
//        int cameraHeight = cameraManager.getCameraResolution().x;

        /** 获取布局中扫描框的位置信息 */
        int[] location = new int[2];
        scanCropView.getLocationInWindow(location);

        int cropLeft = location[0];
        int cropTop = location[1] - StatusBarHeight;

        int cropWidth = scanCropView.getWidth();
        int cropHeight = scanCropView.getHeight();

        /** 获取布局容器的宽高 */
        int containerWidth = scanContainer.getWidth();
        int containerHeight = scanContainer.getHeight();

        /** 计算最终截取的矩形的左上角顶点x坐标 */
        int x = cropLeft * cameraWidth / containerWidth;
        /** 计算最终截取的矩形的左上角顶点y坐标 */
        int y = cropTop * cameraHeight / containerHeight;

        /** 计算最终截取的矩形的宽度 */
        int width = cropWidth * cameraWidth / containerWidth;
        /** 计算最终截取的矩形的高度 */
        int height = cropHeight * cameraHeight / containerHeight;

        /** 生成最终的截取的矩形 */
        Rect mCropRect = new Rect(x, y, width + x, height + y);
        return mCropRect;
    }


    /**
     * 初始化截取的矩形区域
     */
    public Rect getQRCodeRect(ImageView scanCropView, View scanContainer, int cameraWidth, int cameraHeight, int StatusBarHeight) {
//        int cameraWidth = cameraManager.getCameraResolution().y;
//        int cameraHeight = cameraManager.getCameraResolution().x;

        /** 获取布局中扫描框的位置信息 */
        int[] location = new int[2];
        scanCropView.getLocationInWindow(location);

        int cropLeft = location[0];
        int cropTop = location[1] - StatusBarHeight;

        int cropWidth = scanCropView.getWidth();
        int cropHeight = scanCropView.getHeight();

        /** 获取布局容器的宽高 */
        int containerWidth = scanContainer.getWidth();
        int containerHeight = scanContainer.getHeight();

        /** 计算最终截取的矩形的左上角顶点x坐标 */
        int x = cropLeft * cameraWidth / containerWidth;
        /** 计算最终截取的矩形的左上角顶点y坐标 */
        int y = cropTop * cameraHeight / containerHeight;

        /** 计算最终截取的矩形的宽度 */
        int width = cropWidth * cameraWidth / containerWidth;
        /** 计算最终截取的矩形的高度 */
        int height = cropHeight * cameraHeight / containerHeight;

        /** 生成最终的截取的矩形 */
        Rect mCropRect = new Rect(x, y, width + x, height + y);
        return mCropRect;
    }


}
